package com.test.factory;

import com.test.BeanReference;
import com.test.adapter.DisposableBeanAdapter;
import com.test.aware.BeanFactoryAware;
import com.test.aware.BeanNameAware;
import com.test.bean.DisposableBean;
import com.test.bean.InitializingBean;
import com.test.definition.BeanDefinition;
import com.test.exception.BeansException;
import com.test.processor.BeanPostProcessor;
import com.test.value.PropertyValue;
import com.test.value.PropertyValues;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * 自动装配功能的抽象bean工厂
 * 提供了创建和初始化bean的基础设施，支持依赖注入和生命周期回调
 */
public class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{

/*    // 注册销毁方法回调
// 此方法用于注册一个可销毁的bean，如果bean是单例且实现了DisposableBean接口或定义了销毁方法，则进行注册
    registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);*/

    /**
     * 在Bean初始化之前应用BeanPostProcessor
     * 此方法遍历所有BeanPostProcessor，并调用它们的postProcessBeforeInitialization方法
     * 如果任何一个BeanPostProcessor返回null，则停止处理并返回当前的Bean
     *
     * @param existingBean 待处理的Bean
     * @param beanName Bean的名称
     * @return 处理后的Bean
     * @throws Exception 可能抛出的异常
     */
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws Exception {
        Object result = existingBean;
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            Object current = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

    /**
     * 在Bean初始化之后应用BeanPostProcessor
     * 此方法遍历所有BeanPostProcessor，并调用它们的postProcessAfterInitialization方法
     * 如果任何一个BeanPostProcessor返回null，则停止处理并返回当前的Bean
     *
     * @param existingBean 待处理的Bean
     * @param beanName Bean的名称
     * @return 处理后的Bean
     * @throws Exception 可能抛出的异常
     */
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws Exception {
        Object result = existingBean;
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            Object current = beanPostProcessor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

    /**
     * 如果必要，注册一个可销毁的Bean
     * 此方法检查Bean是否是单例，并且是否实现了DisposableBean接口或定义了销毁方法
     * 如果条件满足，则注册Bean以便在容器关闭时调用其销毁方法
     *
     * @param beanName Bean的名称
     * @param bean Bean实例
     * @param beanDefinition Bean的定义
     */
    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
        if (!beanDefinition.isSingleton()){
            return;
        }
        if (bean instanceof DisposableBean || (beanDefinition.getDestroyMethodName() != null && !beanDefinition.getDestroyMethodName().isEmpty())){
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition.getDestroyMethodName()));
        }
    }


    /**
     * 检查是否包含指定名称的bean定义
     * 此方法在当前上下文中未实现
     *
     * @param beanName 要检查的bean名称
     * @return 总是返回false
     */
    @Override
    protected boolean containsBeanDefinition(String beanName) {
        return false;
    }

    /**
     * 获取指定名称的bean的定义信息
     * 此方法在当前上下文中未实现
     *
     * @param beanName 要获取定义信息的bean名称
     * @return 总是返回null
     * @throws BeansException 如果获取定义信息失败
     */
    @Override
    protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
        return null;
    }

    /**
     * 创建并初始化一个bean实例
     * 包括实例化、设置属性值、初始化方法调用等步骤
     *
     * @param beanName       bean的名称
     * @param beanDefinition bean的定义信息
     * @param args           用于构造函数的参数
     * @return 创建并初始化后的bean实例
     * @throws BeansException 如果创建或初始化bean失败
     */
    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {
        Object bean = null;
        try {
            // 创建bean实例
            bean = createBeanInstance(beanDefinition, beanName, args);

            // 应用属性值到bean实例
            applyPropertyValues(beanName, bean, beanDefinition);

            // 初始化bean
            bean = initializeBean(beanName, bean, beanDefinition);

            //注册销毁方法（如果Bean需要销毁）
            registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
        }catch (Exception e){
            throw new BeansException("bean实例创建失败", e);
        }

        // 如果是单例bean，则注册到单例缓存中
        if (beanDefinition.isSingleton()){
            registrySingleton(beanName, bean);
        }

        return bean;
    }

    /**
     * 创建一个bean的实例
     * 根据bean定义中的信息和提供的参数选择合适的构造函数进行实例化
     *
     * @param beanDefinition bean的定义信息
     * @param beanName       bean的名称
     * @param args           用于构造函数的参数
     * @return 创建的bean实例
     * @throws BeansException 如果创建bean实例失败
     */
    private Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
        Constructor<?> constructorToUse = null;
        Class<?> beanClass = beanDefinition.getBeanClass();
        Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();

        // 根据传入参数选择合适的构造函数
        if (args != null && args.length > 0){
            for (Constructor<?> ctor : declaredConstructors) {
                if (args.length == ctor.getParameterTypes().length){
                    constructorToUse = ctor;
                    break;
                }
            }
        }else {
            try {
                // 如果没有参数，尝试使用无参构造函数
                return beanClass.getDeclaredConstructor().newInstance();
            }catch (Exception e){
                throw new BeansException("创建bean实例失败： " + beanName, e);
            }
        }
        try {
            // 使用选定的构造函数创建bean实例
            return constructorToUse.newInstance(args);
        }catch (Exception e){
            throw new BeansException("创建bean实例失败: " + beanName, e);
        }
    }

    /**
     * 应用bean的属性值
     * 将bean定义中指定的属性值设置到bean实例中
     *
     * @param beanName       bean的名称
     * @param bean           bean实例
     * @param beanDefinition bean的定义信息
     * @throws BeansException 如果设置属性值失败
     */
    protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            if (propertyValues.isEmpty()){
                return;
            }
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                String name = propertyValue.getName();
                Object value = propertyValue.getValue();

                // 获取并转换属性值
                Object valueToUse = propertyValue.getConvertedValue();
                if (valueToUse == null) {
                    valueToUse = value;
                }

                // 获取字段信息
                Field field = bean.getClass().getDeclaredField(name);
                field.setAccessible(true);

                // 🔥 进行类型转换
                Class<?> fieldType = field.getType();
                if (valueToUse instanceof String) {
                    valueToUse = convertType((String) valueToUse, fieldType);
                }

                if (valueToUse instanceof BeanReference){
                    BeanReference beanReference = (BeanReference) valueToUse;
                    valueToUse = getBean(beanReference.getBeanName());
                }

                // 设置属性值到bean实例
                field.set(bean, valueToUse);
            }
        }catch (Exception e){
            throw new BeansException("填充bean属性失败: " + beanName, e);
        }
    }

    /**
     * 初始化bean
     * 包括调用初始化方法
     *
     * @param beanName       bean的名称
     * @param bean           bean实例
     * @param beanDefinition bean的定义信息
     * @return 初始化后的bean实例
     * @throws BeansException 如果初始化bean失败
     */
    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
        if (bean instanceof BeanNameAware){
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanFactoryAware){
            ((BeanFactoryAware) bean).setBeanFactory(this);
        }

        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
        try {
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        }catch (Exception e){
            throw new BeansException("执行bean初始化失败：" + beanName, e);
        }

        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        return wrappedBean;
    }

    /**
     * 调用bean的初始化方法
     * 根据bean定义中的初始化方法名称调用相应的方法
     *
     * @param beanName       bean的名称
     * @param bean           bean实例
     * @param beanDefinition bean的定义信息
     * @throws BeansException 如果调用初始化方法失败
     */
    private void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
        if (bean instanceof InitializingBean){
            ((InitializingBean) bean).afterPropertiesSet();
            System.out.println("执行bean[" + beanName + "]的InitializingBean接口的afterPropertiesSet方法");
        }
        String initMethodName = beanDefinition.getInitMethodName();
        if (initMethodName != null && !initMethodName.isEmpty() && !(bean instanceof InitializingBean && initMethodName.equals("afterPropertiesSet"))){
            try {
                // 调用初始化方法
                bean.getClass().getMethod(initMethodName).invoke(bean);
                System.out.println("执行bean[" + beanName + "]的自定义初始化方法: " + initMethodName);
            }catch (Exception e){
                throw new BeansException("初始化bean失败: " + beanName, e);
            }
        }
    }

    /**
     * 🔥 类型转换方法
     */
    private Object convertType(String value, Class<?> targetType) {
        if (targetType == int.class || targetType == Integer.class) {
            return Integer.parseInt(value);
        } else if (targetType == long.class || targetType == Long.class) {
            return Long.parseLong(value);
        } else if (targetType == double.class || targetType == Double.class) {
            return Double.parseDouble(value);
        } else if (targetType == float.class || targetType == Float.class) {
            return Float.parseFloat(value);
        } else if (targetType == boolean.class || targetType == Boolean.class) {
            return Boolean.parseBoolean(value);
        } else if (targetType == String.class) {
            return value;
        }
        throw new IllegalArgumentException("不支持的类型：" + targetType.getName());
    }

    @Override
    public <T> T getBean(String name, Object... args) throws BeansException {
        return (T) getBean(name, args);
    }
}
